package com.sfh.gd.service.rule.impl;

import com.sfh.gd.domain.entity.GamePKDO;
import com.sfh.gd.domain.entity.GameTeamDO;
import com.sfh.gd.service.rule.RuleFactory;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class PKArrangeA implements RuleFactory.Pk {

    List<GamePKDO> pkTeams = new ArrayList<>();

    @Override
    public List<GamePKDO> pkResult( Map<String, GameTeamDO> waiting) {
        // 1.小于2的直接返回
        if (waiting == null || waiting.size() < 2) {
            return null;
        }
        // 2.先按积分分组
        Map<Long, List<GameTeamDO>> scoreGroups = new HashMap<>();
        for (GameTeamDO team : waiting.values()) {
            //队伍积分值
            long score = team.getScoreValue() != null ? team.getScoreValue() : 0;
            scoreGroups.computeIfAbsent(score, k -> new ArrayList<>()).add(team);
        }

        //3. 按等待时间排序每个积分组,同积分优先配对（先等待先配对）
        this.pkTeam(scoreGroups,waiting);

        // 4.未配对队伍，是否存在上一轮未匹配队伍，存在则分组积分值=队伍积分值-未匹配次数 * 10分组
        if (waiting.size() > 2) {
            //清空分组,重新分组
            scoreGroups.clear();
            for (GameTeamDO team : waiting.values()) {
                //未匹配中次数
                long unMatchedCount = team.getUnPkCount() != null ? team.getUnPkCount() : 0;
                long groupScore = team.getScoreValue() != null ? team.getScoreValue() : 0;
                if (unMatchedCount > 0) {
                    //分组积分值
                    groupScore = groupScore - unMatchedCount * 10;
                }
                scoreGroups.computeIfAbsent(groupScore, k -> new ArrayList<>()).add(team);
            }
            //同积分优先配对
            this.pkTeam(scoreGroups,waiting);
        }
        // 5.未配对队伍进行标记在,进入0下一轮PK匹配
        if (waiting.size() > 0) {
            for (GameTeamDO team : waiting.values()) {
                team.setUnPkCount(team.getUnPkCount() != null ? team.getUnPkCount() + 1 : 1);
            }
        }
        return pkTeams;
    }

    private void pkTeam(Map<Long, List<GameTeamDO>> scoreGroups, Map<String, GameTeamDO> waiting) {
        // 按等待时间排序每个积分组（先等待先配对）
        for (List<GameTeamDO> teams : scoreGroups.values()) {
            teams.sort((t1, t2) -> {
                LocalDateTime time1 = t1.getWaitingTime() != null ? t1.getWaitingTime() : LocalDateTime.now();
                LocalDateTime time2 = t2.getWaitingTime() != null ? t2.getWaitingTime() : LocalDateTime.now();
                return time1.compareTo(time2);
            });
        }
        //同积分优先配对
        for (List<GameTeamDO> teams : scoreGroups.values()) {
            for (int i = 0; i < teams.size() - 1; i += 2) {
                GameTeamDO teamA = teams.get(i);
                GameTeamDO teamB = teams.get(i + 1);
                //匹配成功
                GamePKDO pkDO = this.createPK(teamA, teamB);
                pkTeams.add(pkDO);
                //删除等待排队列表已配对队伍
                waiting.remove(String.valueOf(teamA.getId()));
                waiting.remove(String.valueOf(teamB.getId()));
            }
        }
    }

    private GamePKDO createPK(GameTeamDO teamA, GameTeamDO teamB) {
        // 随机分配队伍座位方向：0: A组东西，B组南北；1: A组南北，B组东西
        int direction = (int) (Math.random() * 2);
        teamA.setState(3);
        teamB.setState(3);

        GamePKDO pkDO = new GamePKDO();
        pkDO.setTabNo("");// 桌号 暂不处理
        pkDO.setState(1);
        pkDO.setGameId(teamA.getGameId());
        pkDO.setTeamA(teamA);
        pkDO.setTeamAId(teamA.getId());
        pkDO.setTeamAPoints(teamA.getScoreValue());
        pkDO.setTeamB(teamB);
        pkDO.setTeamBId(teamB.getId());
        pkDO.setTeamBPoints(teamB.getScoreValue());
        pkDO.setRoundCount(Math.max(teamA.getRoundCount(), teamB.getRoundCount()));// 轮数
        if (direction == 0) {
            //0: A组东西，B组南北
            pkDO.setEastId(teamA.getTeamUser1Id());//A组东座位
            pkDO.setWestId(teamA.getTeamUser2Id());//A组西座位
            pkDO.setSouthId(teamB.getTeamUser1Id());//B组南座位
            pkDO.setNorthId(teamB.getTeamUser2Id());//B组北座位
        } else {
            //1: A组南北，B组东西
            pkDO.setSouthId(teamA.getTeamUser1Id());//A组南座位
            pkDO.setNorthId(teamA.getTeamUser2Id());//A组北座位
            pkDO.setEastId(teamB.getTeamUser1Id());//B组东座位
            pkDO.setWestId(teamB.getTeamUser2Id());//B组西座位
        }
        return pkDO;
    }
}
